package org.example.aspect;


import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.example.annotation.DatasourceAnnotation;
import org.example.util.DynamicDatasourceContextHolder;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;


/**
 * @author Donald
 * @create 2020-04-18 22:28
 */
@Aspect
@Component
@Order(-1) // 切面优先于 @transational 执行
public class DynamicDatasourceAspect {

    @Pointcut("execution(* org.example.service.impl.*.* (..))")
    public void ponitcut() {
    }

    /**
     * 设置数据源
     *
     * @param point
     */
    //@Before("@within(dataSource) || @annotation(dataSource)||execution(* org.example.service.impl..*.* (..))")
    //public void switchDatasource(JoinPoint point, DatasourceAnnotation dataSource)
    @Before("ponitcut()")
    public void switchDatasource(JoinPoint point) {
        DatasourceAnnotation dataSource;
        Object target = point.getTarget();
        Method method = ((MethodSignature) point.getSignature()).getMethod();

        // 1. 方法是否被数据源注解
        if(method.isAnnotationPresent(DatasourceAnnotation.class)){
            DatasourceAnnotation annotation = method.getAnnotation(DatasourceAnnotation.class);
            if( DynamicDatasourceContextHolder.containDataSourceKey(annotation.value())){
                DynamicDatasourceContextHolder.setDatasourceKey(annotation.value());
                System.out.println("设置方法的数据源>>> "+ annotation.value());
                return;
            }
        }

        // 2. 类上的注解
        if (target.getClass().isAnnotationPresent(DatasourceAnnotation.class)){
            DatasourceAnnotation annotation = target.getClass().getAnnotation(DatasourceAnnotation.class);
            if( DynamicDatasourceContextHolder.containDataSourceKey(annotation.value())){
                DynamicDatasourceContextHolder.setDatasourceKey(annotation.value());
                System.out.println("设置实现类的数据源>>> "+ annotation.value());
                return;
            }
        }

        // 3. 获取请求头里面的 数据源
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        String dataSourceName = request.getHeader("dataSourceName");
        if(DynamicDatasourceContextHolder.containDataSourceKey(dataSourceName)){
            DynamicDatasourceContextHolder.setDatasourceKey(dataSourceName);
            System.out.println("设置请求头的数据源>>> "+ dataSourceName);
            return;
        }

        System.out.println("默认数据源 ："+ DynamicDatasourceContextHolder.getDatasourceKey());
    }

   // @After("@within(dataSource)||@annotation(dataSource)")
    @After("ponitcut()")
    public void resetDatasource(JoinPoint point) {
        // 将数据源置为默认数据源
        DynamicDatasourceContextHolder.clearDataSourceKey();
    }

}
